package com.hjx.windowtool.photo2video;

import java.awt.EventQueue;
import java.awt.FileDialog;

import javax.swing.JFrame;
import javax.swing.JTabbedPane;
import java.awt.BorderLayout;
import javax.swing.JPanel;
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.UIManager;

import com.hjx.windowtool.db.Tool;
import com.hjx.windowtool.photo2video.JavacvUtils.JavacvCallback;
import com.hjx.windowtool.util.StrUtil;

import javax.swing.JButton;
import javax.swing.JFileChooser;

import java.awt.event.ActionListener;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import java.awt.event.ActionEvent;
import javax.swing.JProgressBar;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JSplitPane;
import java.awt.FlowLayout;
import javax.swing.JMenuBar;
import javax.swing.JMenu;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.JMenuItem;
import javax.swing.JOptionPane;
import javax.swing.JCheckBoxMenuItem;
@Tool("图片视频互转")
public class JavacvPhoto2VideoApp {
	
	private boolean closeComputer=false;

	private JFrame frame;
	private JTextField textField;
	private JTextField textField_1;
	private JProgressBar progressBar;
	private JTextArea txtMsg;
	private JTextField textField_2;
	private JTextField textField_3;
	private JTextField textField_4;

	private JButton btn_toimg;

	/**
	 * Launch the application.
	 */
	public static void main(String[] args) {
		EventQueue.invokeLater(new Runnable() {
			public void run() {
				try {
					UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
					JavacvPhoto2VideoApp window = new JavacvPhoto2VideoApp();
					window.frame.setVisible(true);
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		});
	}

	/**
	 * Create the application.
	 */
	public JavacvPhoto2VideoApp() {
		initialize();
	}

	/**
	 * Initialize the contents of the frame.
	 */
	private void initialize() {
		frame = new JFrame();
		frame.setTitle("图片视频互转");
		frame.setBounds(100, 100, 509, 335);
		frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
		
		JSplitPane splitPane = new JSplitPane();
		splitPane.addComponentListener(new ComponentAdapter() {
			@Override
			public void componentResized(ComponentEvent e) {
				System.out.println("splitPane is componentResized "+splitPane.getBounds());
				splitPane.setResizeWeight(145d/(splitPane.getBounds().height*1d));
			}
		});
		splitPane.setResizeWeight(0.5);
		splitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
		frame.getContentPane().add(splitPane, BorderLayout.CENTER);
		
		JPanel panel_2 = new JPanel();
		splitPane.setLeftComponent(panel_2);
		panel_2.setLayout(new BorderLayout(0, 0));
		
		JTabbedPane tabbedPane = new JTabbedPane(JTabbedPane.TOP);
		panel_2.add(tabbedPane);
		
		JPanel panel = new JPanel();
		tabbedPane.addTab("视频转图片", null, panel, null);
		panel.setLayout(null);
		
		JLabel label = new JLabel("视频路径");
		label.setBounds(10, 10, 54, 15);
		panel.add(label);
		
		textField = new JTextField();
		textField.setBounds(69, 7, 285, 21);
		panel.add(textField);
		textField.setColumns(10);
		
		JButton button = new JButton(".");
		button.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String file = selectFile();
				if (file==null) {
					return;
				}
				textField.setText(file);
				textField_3.setText(file);
			}
		});
		button.setBounds(357, 7, 19, 23);
		panel.add(button);
		
		JLabel label_1 = new JLabel("视频片段");
		label_1.setBounds(10, 39, 54, 15);
		panel.add(label_1);
		
		textField_1 = new JTextField();
		textField_1.setBounds(69, 38, 285, 21);
		panel.add(textField_1);
		textField_1.setColumns(10);
		
		JButton button_1 = new JButton("...");
		button_1.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String selectDir = selectDir();
				if (selectDir==null) {
					return;
				}
				textField_1.setText(selectDir);
			}
		});
		button_1.setBounds(357, 35, 19, 23);
		panel.add(button_1);
		
		btn_toimg = new JButton("转换图片");
		btn_toimg.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String videoPart = textField_1.getText();
				if (StrUtil.isEmpty(videoPart)) {
					new Thread(new Runnable() {
						public void run() {
							try {
								btn_toimg.setEnabled(false);
								JavacvUtils.call = new JavacvUtils.JavacvCallback() {
									@Override
									public int msg(int totalFrames, int runSize, String msg) {
										progressBar.setMaximum(totalFrames);
										progressBar.setValue(runSize);
										String str = totalFrames + ":"+runSize+"=" + msg;
										apendMsg(str);
										if (runSize>=totalFrames-3) {
											btn_toimg.setEnabled(true);
											onScuccess();
										}
										return 0;
									}
									public void error(Throwable e) {
										apendMsg("视频转图片时发生错误！" + e);
										btn_toimg.setEnabled(true);
									}
								};
								String movie = textField.getText();
								File out = new File(movie.substring(0, movie.lastIndexOf(".")));
								if (!out.exists()) {
									out.mkdirs();
								}
								JavacvUtils.extractImages(movie, out.getAbsolutePath());
							} catch (Exception e1) {
								apendMsg("视频转图片时发生错误！"+e1);
							}finally{
								onScuccess();
							}
						}
						
					}).start();
				}else {
					getImagesByParts(textField.getText(),videoPart);
				}
				
			}
		});
		btn_toimg.setBounds(69, 69, 93, 23);
		panel.add(btn_toimg);
		
		JButton button_2 = new JButton("提取视频");
		button_2.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				Runnable runnable = new Runnable() {
					public void run() {
						String videoPart = textField_1.getText();
						getVideoByParts(textField.getText(), videoPart);
					}
				};
				new Thread(runnable).start();
			}
		});
		button_2.setBounds(172, 69, 93, 23);
		panel.add(button_2);
		
		JPanel panel_1 = new JPanel();
		tabbedPane.addTab("图片转视频", null, panel_1, null);
		panel_1.setLayout(null);
		
		JLabel label_2 = new JLabel("图片文件夹");
		label_2.setBounds(10, 10, 65, 15);
		panel_1.add(label_2);
		
		textField_2 = new JTextField();
		textField_2.setBounds(79, 7, 261, 21);
		panel_1.add(textField_2);
		textField_2.setColumns(10);
		
		JButton button_3 = new JButton("选择");
		button_3.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String dir = selectDir();
				if (dir==null) {
					return;
				}
				textField_2.setText(dir);
			}
		});
		button_3.setBounds(350, 6, 57, 23);
		panel_1.add(button_3);
		
		JLabel label_3 = new JLabel("原视频");
		label_3.setBounds(10, 35, 54, 15);
		panel_1.add(label_3);
		
		textField_3 = new JTextField();
		textField_3.setBounds(79, 32, 261, 21);
		panel_1.add(textField_3);
		textField_3.setColumns(10);
		
		JButton button_4 = new JButton("选择");
		button_4.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				String file = selectFile();
				if (file==null) {
					return;
				}
				textField.setText(file);
				textField_3.setText(file);
			}
		});
		button_4.setBounds(350, 31, 57, 23);
		panel_1.add(button_4);
		
		JLabel label_4 = new JLabel("输出帧率");
		label_4.setToolTipText("");
		label_4.setBounds(10, 60, 54, 15);
		panel_1.add(label_4);
		
		textField_4 = new JTextField();
		textField_4.setToolTipText("0表示跟原视频");
		textField_4.setText("0");
		textField_4.setBounds(79, 57, 261, 21);
		panel_1.add(textField_4);
		textField_4.setColumns(10);
		
		final JButton button_6 = new JButton("替换帧");
		button_6.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				new Thread(new Runnable() {
					public void run() {
						try {
							button_6.setEnabled(false);
							JavacvUtils.call = new JavacvUtils.JavacvCallback() {
								@Override
								public int msg(int totalFrames, int runSize, String msg) {
									progressBar.setMaximum(totalFrames);
									progressBar.setValue(runSize);
									apendMsg(totalFrames + ":" + msg);
									return 0;
								}
								public void error(Throwable e) {
									apendMsg("替换帧时发生错误:" + e);
								}
							};
							String dirPath = textField_2.getText();
							String oldMov = textField_3.getText();
							String frameRateString = textField_4.getText();
							JavacvUtils.recorderImages(dirPath, oldMov, Double.valueOf(frameRateString));
						} catch (Exception e1) {
							e1.printStackTrace();
							apendMsg("替换帧时发生错误:" + e1);
						} finally {
							button_6.setEnabled(true);
						}
					}
				}).start();
			}
		});
		button_6.setBounds(79, 85, 93, 23);
		panel_1.add(button_6);
		
		JPanel panel_3 = new JPanel();
		splitPane.setRightComponent(panel_3);
		panel_3.setLayout(new BorderLayout(0, 0));
		
		progressBar = new JProgressBar();
		progressBar.setStringPainted(true);
		panel_3.add(progressBar, BorderLayout.SOUTH);
		
		JScrollPane scrollPane_1 = new JScrollPane();
		panel_3.add(scrollPane_1, BorderLayout.CENTER);
		
		txtMsg = new JTextArea();
		scrollPane_1.setViewportView(txtMsg);
		
		JMenuBar menuBar = new JMenuBar();
		frame.setJMenuBar(menuBar);
		
		JMenu menu = new JMenu("菜单");
		menuBar.add(menu);
		
		JMenuItem menuItem = new JMenuItem("退出");
		menuItem.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				System.exit(0);
			}
		});
		
		JCheckBoxMenuItem checkBoxMenuItem = new JCheckBoxMenuItem("转换完后自动关机");
		checkBoxMenuItem.addActionListener(new ActionListener() {

			public void actionPerformed(ActionEvent e) {
				closeComputer = checkBoxMenuItem.isSelected();
			}
		});
		menu.add(checkBoxMenuItem);
		menu.add(menuItem);
		
	}
	protected void getVideoByParts(String videoPath,String videoPart) {

		try {
			JavacvUtils.pSize.set(0);
			long movieLength[]=JavacvUtils.getMovieFrameAndTimeLength(videoPath);
			if (movieLength==null) {
				apendMsg("获取视频信息失败！");
				return;
			}
			long totalFrames=movieLength[0];
			long totalTime=movieLength[1];
			double frameTime=totalTime/(totalFrames*1d);
			System.out.println(movieLength[0]+"========"+movieLength[1]+"=="+frameTime);
			if (StrUtil.isEmpty(videoPart)) {
				File file = new File(videoPath.substring(0, videoPath.lastIndexOf("."))+".txt");
				if (file.exists()) {
					videoPart=Files.readAllLines(file.toPath()).get(0);
				}else {
					return;
				}
			}
			String[] parts = videoPart.split(";");
			AtomicInteger frames=new AtomicInteger(0);
			JavacvUtils.call=new JavacvCallback() {
				@Override
				public int msg(int totalFrames, int runSize, String msg) {
					progressBar.setMaximum((int) frames.get());
					progressBar.setValue(runSize);
					String str = frames + ":" + msg;
					apendMsg(str);
					if (runSize>=frames.get()-3) {
						btn_toimg.setEnabled(true);
						onScuccess();
					}
					return 0;
				}
				public void error(Throwable e) {
					apendMsg("视频提取时发生错误！" + e);
					btn_toimg.setEnabled(true);
				}
			};
			String movie = videoPath;
			File out = new File(movie.substring(0, movie.lastIndexOf(".")));
			if (!out.exists()) {
				out.mkdirs();
			}
			
			String toPath=out.getAbsolutePath();
			List<int[]> list=new ArrayList<>();
			for (String part : parts) {
				String[] times = part.split("-");
				if (times.length<2) {
					continue;
				}
				String sStart=times[0];
				String sEnd=times[1];
				long ms=StrUtil.minuteStringToMicrosecond(sStart);
				long me=StrUtil.minuteStringToMicrosecond(sEnd);
				int start=(int) (ms/frameTime-2);
				int end=(int) (me/frameTime+2);
				int size = end-start;
				frames.addAndGet(size);
				list.add(new int[] {start,end});
			}
			JavacvUtils.extractMovie(videoPath, list);
		} catch (Exception e) {
			e.printStackTrace();
		}
	
		
	}
	protected void getImagesByParts(String videoPath,String videoPart) {
		try {
			JavacvUtils.pSize.set(0);
			long movieLength[]=JavacvUtils.getMovieFrameAndTimeLength(videoPath);
			if (movieLength==null) {
				apendMsg("获取视频信息失败！");
				return;
			}
			long totalFrames=movieLength[0];
			long totalTime=movieLength[1];
			double frameTime=totalTime/(totalFrames*1d);
			System.out.println(movieLength[0]+"========"+movieLength[1]+"=="+frameTime);
			String[] parts = videoPart.split(";");
			AtomicInteger frames=new AtomicInteger(0);
			JavacvUtils.call=new JavacvCallback() {
				@Override
				public int msg(int totalFrames, int runSize, String msg) {
					progressBar.setMaximum((int) frames.get());
					progressBar.setValue(runSize);
					String str = frames + ":" + msg;
					apendMsg(str);
					if (runSize>=frames.get()-3) {
						btn_toimg.setEnabled(true);
						onScuccess();
					}
					return 0;
				}
				public void error(Throwable e) {
					apendMsg("视频转图片时发生错误！" + e);
					btn_toimg.setEnabled(true);
				}
			};
			String movie = videoPath;
			File out = new File(movie.substring(0, movie.lastIndexOf(".")));
			if (!out.exists()) {
				out.mkdirs();
			}
			
			String toPath=out.getAbsolutePath();
			for (String part : parts) {
				String[] times = part.split("-");
				if (times.length<2) {
					continue;
				}
				String sStart=times[0];
				String sEnd=times[1];
				long ms=StrUtil.minuteStringToMicrosecond(sStart);
				long me=StrUtil.minuteStringToMicrosecond(sEnd);
				int start=(int) (ms/frameTime-2);
				int end=(int) (me/frameTime+2);
				int size = end-start;
				frames.addAndGet(size);
				JavacvUtils.extractImages(videoPath, toPath, start, size);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private void onScuccess() {
		if (closeComputer) {
			try {
				Runtime.getRuntime().exec("shutdown -s -t 10");
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			} 
		}
	}
	/**
	 * @param str
	 */
	public void apendMsg(String str) {
		txtMsg.append(str+"\t\n");
		txtMsg.setCaretPosition(txtMsg.getText().length());
	}
	/**
	 * 
	 */
	public String selectFile() {
		FileDialog f=new FileDialog(frame);
		f.setVisible(true);
		String file = f.getFile();
		if (file==null) {
			return null;
		}
		return f.getDirectory()+"\\"+file;
	}
	/**
	 * 
	 */
	public String selectDir() {
		JFileChooser jf=new JFileChooser();
		jf.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int showOpenDialog = jf.showOpenDialog(frame);
		if (showOpenDialog!=0) {
			return null;
		}
		File file = jf.getSelectedFile();
		return (file.getAbsolutePath());
	}
}
